import Utils, { ArrayUtils } from "../core/utils";

export class CoordMap<T> {
    col = 0;
    row = 0;
    protected _map: T[][] = [];
    constructor(col, row, def: T = null) {
        this.row = row;
        this.col = col;

        this._map = [];
        for (let r = 0; r < this.row; r++) {
            let row = [];
            for (let c = 0; c < this.col; c++) {
                row.push(def);
            }
            this._map.push(row);
        }
    }
    get map() {
        return this._map;
    }

    forEach(func: (ele: T, c: number, r: number) => boolean) {
        for (let r = 0; r < this._map.length; r++) {
            for (let c = 0; c < this._map[r].length; c++) {
                if (func(this._map[r][c], c, r) === false) {
                    break;
                }
            }
        }
    }

    contains(cr: cc.Vec2) {
        return cr.x >= 0 && cr.y >= 0 && cr.x < this.col && cr.y < this.row;
    }
    set(c: number, r: number, value: T) {
        let row = this.getRow(r);
        row[c] = value;
    }
    get(c: number, r: number): T {
        let row = this.getRow(r);
        return row[c] || null;
    }

    has(c: number, r: number): boolean {
        let row = this.getRow(r);
        return !!row[c];
    }

    delete(c: number, r: number): boolean {
        let row = this.getRow(r);
        return row[c] = null;
    }

    getRow(r: number): T[] {
        if (!this._map[r]) {
            this._map[r] = [];
        }
        return this._map[r];
    }

    //设置一整行
    setRow(r: number, value: T) {
        this._map[r] = this.__fill(this.col, value);
    }
    //设置一整列
    setCol(c: number, value: T) {
        for (let r = 0; r < this.row; r++) {
            this._map[r][c] = Utils.cloneDeep(value);
        }
    }
    deleteRow(r: number) {
        this._map[r] = [];
    }
    private __fill(count: number, def: T) {
        return ArrayUtils.Fill(count, def);
    }
    trimRow(dstRow: number, def: T = null) {
        let out: T[][] = [];
        if (this.row < dstRow) {
            let delta = dstRow - this.row;
            let arr2: T[][] = new Array(delta);
            for (let i = 0; i < arr2.length; i++) {
                arr2[i] = this.__fill(this.col, def);
            }
            this._map = this._map.concat(arr2);
        }
        else if (this.row > dstRow) { //srcRow > dstRow
            out = this._map.splice(dstRow)
            // this._map = this._map.slice(0, dstRow);
        }
        this.row = dstRow;
        return out;
    }
    trimCol(dstCol: number, def: T = null) {
        let out: T[][] = [];
        if (this.col < dstCol) {
            let delta = dstCol - this.col;
            for (let r = 0; r < this._map.length; r++) {
                let row = this.__fill(delta, def);
                this._map[r] = this._map[r].concat(row);
            }
        }
        else if (this.col > dstCol) { //srcRow > dstRow
            for (let r = 0; r < this._map.length; r++) {
                out.push(this._map[r].splice(dstCol));
                // this._map[r] = this._map[r].slice(0, dstCol);
            }
        }
        this.col = dstCol;
        return out;
    }
};